from collections import deque
from threading import Thread, Event, Timer
from kivy.clock import Clock
from time import sleep

class IntervalService(Thread):
    def __init__(self, on_success=None, on_error=None, timeout=5):
        Thread.__init__(self)
        self._queue = deque()
        self._trigger_result = Clock.create_trigger(self._dispatch_result, 0)
        self.daemon = True
        self.on_success = on_success
        self.on_error = on_error
        self._result = None
        self._error = None
        self._is_finished = False
        self._resp_status = None
        
        self.exit_flag = Event()
        self.sleeping = Event()
        self.timeout = timeout

        self.start()

    def run(self):
        while not self.exit_flag.is_set():
            q = self._queue.appendleft
            e= None
            try:
                result = self.do()
            except Exception, e:
                pass

            if e is not None:
                q(('error', e))
            else:
                q(('success', result))

            self._trigger_result()
            
            #Lets doze
            self.sleeping.clear()
            self.t = Timer(self.timeout, self.sleeping.set)
            self.t.start()
            self.sleeping.wait()
    
    def exit(self):
        self.exit_flag.set()
        self.sleeping.set()
        self.t.cancel()
    
    def _dispatch_result(self, dt):
        while True:
            # Read the result pushed on the queue, and dispatch to the client
            try:
                result, data = self._queue.pop()
            except IndexError:
                return
            if result == 'success':
                self._is_finished = True
                self._result = data
                if self.on_success:
                    self.on_success(self, data)
            elif result == 'error':
                self._is_finished = True
                self._error = data
                if self.on_error:
                    self.on_error(self, data)
            else:
                assert(0)

    @property
    def is_finished(self):
        return self._is_finished

    @property
    def result(self):
        return self._result


    @property
    def error(self):
        return self._error

from Pyro.EventService.Clients import Subscriber

class EventService(Thread, Subscriber):
  def __init__(self, match):
    Thread.__init__(self)
    Subscriber.__init__(self)
    self._queue = deque()
    self._trigger_result = Clock.create_trigger(self._dispatch_result, 0)
    self.match = match
 
  def run(self):
    self.subscribeMatch(self.match)
    self.listen()
    
  def event(self,event):
    q = self._queue.appendleft
    q(('success', event))
    self._trigger_result()
      
  def _dispatch_result(self, dt):
    try:
      result, event = self._queue.pop()
    except IndexError:
      return
    self.on_event(event)
